Utilisation de Symfony UX
Utiliser un composant Symfony UX pour créer des graphiques avec ux-chartjs
Notions théoriques
Qu'est-ce que ux-chartjs ?
symfony/ux-chartjs est un composant officiel de Symfony UX qui permet de créer des graphiques interactifs dans une application Symfony, en écrivant uniquement du code PHP et Twig. Il encapsule la bibliothèque JavaScript Chart.js — l'une des plus populaires au monde pour la visualisation de données — et l'expose via une API PHP simple et cohérente avec l'écosystème Symfony.
Sans ux-chartjs, intégrer Chart.js dans une application Symfony nécessiterait d'écrire manuellement du JavaScript, de gérer les données côté client, et de maintenir une synchronisation entre le backend PHP et le frontend JS. Avec ux-chartjs, tout se fait côté PHP : les données, le type de graphique, les couleurs, les options — et Chart.js s'occupe du rendu automatiquement dans le navigateur.
Les types de graphiques disponibles
Chart.js, et donc ux-chartjs, supporte plusieurs types de graphiques, tous accessibles via des constantes PHP :
| Constante PHP | Type de graphique |
|---|---|
Chart::TYPE_BAR | Barres verticales |
Chart::TYPE_LINE | Courbes / lignes |
Chart::TYPE_PIE | Camembert |
Chart::TYPE_DOUGHNUT | Anneau |
Chart::TYPE_RADAR | Radar |
Chart::TYPE_POLAR_AREA | Aires polaires |
Chart::TYPE_BUBBLE | Bulles |
Chart::TYPE_SCATTER | Nuage de points |
Pour une première utilisation, les types BAR (barres) et LINE (courbes) sont les plus simples à comprendre et à configurer. Ce sont aussi les plus courants dans les applications de gestion.
La structure des données d'un graphique
La structure des données d'un graphique Chart.js
Tout graphique Chart.js repose sur une structure de données précise. En PHP avec ux-chartjs, cette structure se construit via les méthodes setData() et setOptions() de l'objet Chart.
Les données (setData) se composent de :
labels: un tableau de chaînes de caractères qui constituent les étiquettes de l'axe X (ou les légendes pour un camembert). Exemple :['Janvier', 'Février', 'Mars']datasets: un tableau de jeux de données. Chaque dataset représente une série de valeurs à afficher. Un graphique peut en avoir plusieurs (exemple : ventes 2023 et ventes 2024 superposées).
Chaque dataset contient :
[
'label' => 'Ventes 2024', // Légende de la série
'data' => [120, 85, 200, 160], // Valeurs numériques
'backgroundColor' => 'rgba(54, 162, 235, 0.5)', // Couleur de fond
'borderColor' => 'rgb(54, 162, 235)', // Couleur de bordure
'borderWidth' => 1, // Épaisseur de bordure
]
Les couleurs dans Chart.js s'expriment en rgba (rouge, vert, bleu, opacité) ou en rgb. L'opacité (dernier paramètre de rgba) va de 0 (transparent) à 1 (opaque). Pour les barres, une opacité de 0.5 à 0.8 est souvent esthétique.
Les options de configuration
Les options de configuration avec
setOptions
La méthode setOptions() permet de personnaliser le comportement et l'apparence du graphique. Elle accepte un tableau PHP qui correspond aux options Chart.js :
$chart->setOptions([
'scales' => [
'y' => [
'beginAtZero' => true, // L'axe Y commence à 0
],
],
'plugins' => [
'legend' => [
'position' => 'top', // Position de la légende
],
'title' => [
'display' => true,
'text' => 'Titre du graphique',
],
],
'responsive' => true, // Le graphique s'adapte à la taille du conteneur
]);
Toutes les options disponibles dans Chart.js sont utilisables dans setOptions(). La documentation officielle de Chart.js (https://www.chartjs.org/docs/latest/) liste l'intégralité des options par type de graphique.
Le flux complet : de PHP au navigateur
Voici comment ux-chartjs fonctionne en coulisses, de la création du graphique en PHP jusqu'à son affichage dans le navigateur :
1. Dans le contrôleur PHP
On injecte ChartBuilderInterface et on crée un objet Chart avec ses données et ses options.
2. Dans le template Twig
On appelle la fonction render_chart(chart) qui génère une balise <canvas> HTML avec les données sérialisées en JSON dans un attribut data-*.
3. Dans le navigateur
Stimulus détecte la balise <canvas> via l'attribut data-controller, lit les données JSON, et instancie Chart.js pour afficher le graphique interactif.
PHP (ChartBuilder)
→ Objet Chart (données + options)
→ Twig render_chart()
→ HTML <canvas data-*="...JSON...">
→ Stimulus controller.js
→ Chart.js (rendu visuel)
Pour que render_chart() soit disponible dans Twig, le composant symfony/ux-chartjs doit être installé et la balise {{ importmap('app') }} doit être présente dans base.html.twig. Sans cette balise, le contrôleur Stimulus ne se charge pas et le graphique n'apparaît pas.
L'injection de dépendances
L'injection de dépendances avec ChartBuilderInterface
En Symfony, on ne crée pas d'objets Chart directement avec new Chart(). On passe par une interface : ChartBuilderInterface. Cette interface est injectée automatiquement par le conteneur de services de Symfony dans le constructeur du contrôleur ou directement en paramètre de la méthode du contrôleur.
use Symfony\UX\Chartjs\Builder\ChartBuilderInterface;
use Symfony\UX\Chartjs\Model\Chart;
class StatistiqueController extends AbstractController
{
#[Route('/stats', name: 'app_stats')]
public function index(ChartBuilderInterface $chartBuilder): Response
{
$chart = $chartBuilder->createChart(Chart::TYPE_BAR);
// ...
return $this->render('statistique/index.html.twig', [
'chart' => $chart,
]);
}
}
L'utilisation d'une interface (ChartBuilderInterface) plutôt que d'une classe concrète est une bonne pratique Symfony. Cela permet de remplacer l'implémentation sans modifier le code du contrôleur — c'est le principe d'inversion de dépendances.
Afficher plusieurs graphiques
Afficher plusieurs graphiques sur une même page
Il est tout à fait possible d'afficher plusieurs graphiques sur une même page. Il suffit de créer plusieurs objets Chart dans le contrôleur et de les passer tous au template :
$chartVentes = $chartBuilder->createChart(Chart::TYPE_BAR);
$chartVisites = $chartBuilder->createChart(Chart::TYPE_LINE);
return $this->render('statistique/index.html.twig', [
'chartVentes' => $chartVentes,
'chartVisites' => $chartVisites,
]);
Dans Twig :
{{ render_chart(chartVentes) }}
{{ render_chart(chartVisites) }}
Chaque appel à render_chart() génère une balise <canvas> indépendante, et Stimulus instancie Chart.js séparément pour chacune.
Exemple pratique
Création d'un graphique de ventes
Cet exemple montre comment créer un graphique en barres affichant des ventes mensuelles fictives dans un projet Symfony avec ux-chartjs déjà installé.
Si ux-chartjs n'est pas encore installé, exécuter dans le terminal : composer require symfony/ux-chartjs
Étape 1 — Créer le contrôleur
Dans le terminal VS Code, générer un nouveau contrôleur :
php bin/console make:controller StatistiqueController
Ouvrir le fichier généré src/Controller/StatistiqueController.php et le remplacer par le code suivant :
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\UX\Chartjs\Builder\ChartBuilderInterface;
use Symfony\UX\Chartjs\Model\Chart;
class StatistiqueController extends AbstractController
{
#[Route('/statistiques', name: 'app_statistiques')]
public function index(ChartBuilderInterface $chartBuilder): Response
{
// Création d'un graphique en barres
$chart = $chartBuilder->createChart(Chart::TYPE_BAR);
// Définition des données
$chart->setData([
'labels' => [
'Janvier', 'Février', 'Mars', 'Avril',
'Mai', 'Juin', 'Juillet', 'Août',
'Septembre', 'Octobre', 'Novembre', 'Décembre'
],
'datasets' => [
[
'label' => 'Ventes 2024 (en €)',
'data' => [4200, 3800, 5100, 4700, 6200, 5800, 7100, 6500, 5900, 6800, 7400, 8200],
'backgroundColor' => 'rgba(54, 162, 235, 0.6)',
'borderColor' => 'rgb(54, 162, 235)',
'borderWidth' => 2,
],
],
]);
// Options de configuration
$chart->setOptions([
'responsive' => true,
'plugins' => [
'legend' => ['position' => 'top'],
'title' => [
'display' => true,
'text' => 'Chiffre d\'affaires mensuel 2024',
],
],
'scales' => [
'y' => ['beginAtZero' => true],
],
]);
return $this->render('statistique/index.html.twig', [
'chart' => $chart,
]);
}
}
Étape 2 — Créer le template Twig
Ouvrir le fichier templates/statistique/index.html.twig généré automatiquement et le remplacer par :
{% extends 'base.html.twig' %}
{% block title %}Statistiques de ventes{% endblock %}
{% block body %}
<div style="max-width: 900px; margin: 2rem auto; padding: 0 1rem;">
<h1>Statistiques de ventes 2024</h1>
<p>Voici l'évolution du chiffre d'affaires mois par mois.</p>
{{ render_chart(chart) }}
</div>
{% endblock %}
Étape 3 — Vérifier base.html.twig
Ouvrir templates/base.html.twig et s'assurer que la balise suivante est présente dans le <head> :
{{ importmap('app') }}
Étape 4 — Lancer le serveur et tester
symfony server:start
Ouvrir https://127.0.0.1:8000/statistiques dans le navigateur. Un graphique en barres bleutées doit s'afficher avec les 12 mois de l'année en abscisse et les valeurs de ventes en ordonnée.
Étape 5 — Ajouter une deuxième série de données
Pour comparer deux années, modifier la méthode setData() dans le contrôleur en ajoutant un second dataset :
'datasets' => [
[
'label' => 'Ventes 2023 (en €)',
'data' => [3800, 3200, 4500, 4100, 5600, 5000, 6400, 5900, 5200, 6100, 6700, 7500],
'backgroundColor' => 'rgba(255, 99, 132, 0.6)',
'borderColor' => 'rgb(255, 99, 132)',
'borderWidth' => 2,
],
[
'label' => 'Ventes 2024 (en €)',
'data' => [4200, 3800, 5100, 4700, 6200, 5800, 7100, 6500, 5900, 6800, 7400, 8200],
'backgroundColor' => 'rgba(54, 162, 235, 0.6)',
'borderColor' => 'rgb(54, 162, 235)',
'borderWidth' => 2,
],
],
Rafraîchir la page : le graphique affiche maintenant deux séries de barres côte à côte, avec une légende différenciant 2023 (rouge) et 2024 (bleu).
Aucune modification du template Twig n'est nécessaire pour ajouter une série : tout se gère côté PHP dans le contrôleur. C'est tout l'intérêt de ux-chartjs.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Dans ce TP, vous allez créer un tableau de bord de statistiques fictives pour une boutique en ligne, en affichant 2 graphiques distincts sur une même page :
- un graphique en barres pour les ventes mensuelles
- et un graphique en courbes pour le nombre de visiteurs.
Tout le travail se fait côté PHP et Twig, sans écrire une seule ligne de JavaScript.
Étape 1 — Préparer le projet
Ouvrez un terminal PowerShell ou le terminal intégré de VS Code (Ctrl + ù), naviguez vers votre dossier Documents et créez un nouveau projet Symfony :
cd %USERPROFILE%\Documents
symfony new tp-chartjs --webapp
cd tp-chartjs
code .
Une fois VS Code ouvert sur le projet, installez le composant ux-chartjs :
composer require symfony/ux-chartjs
Vérifiez ensuite que assets/controllers.json contient bien l'entrée pour @symfony/ux-chartjs.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 2 — Vérifier la balise importmap dans base.html.twig
Avant de créer le moindre contrôleur, ouvrez le fichier templates/base.html.twig et localisez la balise <head>. Vérifiez que la ligne suivante est bien présente :
{{ importmap('app') }}
Si elle est absente, ajoutez-la manuellement avant la balise fermante </head>.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 3 — Créer le contrôleur DashboardController
Dans le terminal, générez un contrôleur nommé DashboardController :
php bin/console make:controller DashboardController
Deux fichiers sont créés :
src/Controller/DashboardController.phptemplates/dashboard/index.html.twig
Ouvrez src/Controller/DashboardController.php et remplacez intégralement son contenu par le code suivant, qui crée un premier graphique en barres pour les ventes mensuelles :
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\UX\Chartjs\Builder\ChartBuilderInterface;
use Symfony\UX\Chartjs\Model\Chart;
class DashboardController extends AbstractController
{
#[Route('/dashboard', name: 'app_dashboard')]
public function index(ChartBuilderInterface $chartBuilder): Response
{
$chartVentes = $chartBuilder->createChart(Chart::TYPE_BAR);
$chartVentes->setData([
'labels' => [
'Janvier', 'Février', 'Mars', 'Avril',
'Mai', 'Juin', 'Juillet', 'Août',
'Septembre', 'Octobre', 'Novembre', 'Décembre',
],
'datasets' => [
[
'label' => 'Ventes (en €)',
'data' => [3200, 2800, 4100, 3700, 5200, 4900, 6100, 5500, 4800, 5700, 6300, 7100],
'backgroundColor' => 'rgba(75, 192, 192, 0.6)',
'borderColor' => 'rgb(75, 192, 192)',
'borderWidth' => 2,
],
],
]);
$chartVentes->setOptions([
'responsive' => true,
'plugins' => [
'legend' => ['position' => 'top'],
'title' => [
'display' => true,
'text' => 'Ventes mensuelles de la boutique',
],
],
'scales' => [
'y' => ['beginAtZero' => true],
],
]);
return $this->render('dashboard/index.html.twig', [
'chartVentes' => $chartVentes,
]);
}
}
Une solution
Vous devez être connecté pour voir le contenu.
Étape 4 — Créer le template Twig du dashboard
Ouvrez templates/dashboard/index.html.twig et remplacez son contenu par :
{% extends 'base.html.twig' %}
{% block title %}Tableau de bord{% endblock %}
{% block body %}
<div style="max-width: 960px; margin: 2rem auto; padding: 0 1rem;">
<h1>Tableau de bord — boutique en ligne</h1>
<section style="margin-top: 2rem;">
<h2>Ventes mensuelles</h2>
{{ render_chart(chartVentes) }}
</section>
</div>
{% endblock %}
Lancez ensuite le serveur de développement et vérifiez l'affichage :
symfony server:start
Ouvrez https://127.0.0.1:8000/dashboard dans le navigateur. Le graphique en barres doit s'afficher avec les 12 mois et les valeurs de ventes.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 5 — Ajouter un second graphique en courbes pour les visiteurs
Modifiez le contrôleur DashboardController.php pour créer un second graphique de type LINE, représentant le nombre de visiteurs mensuels. Transmettez ce second graphique au template.
Le second graphique doit :
- Être de type courbe (
Chart::TYPE_LINE) - Avoir les mêmes 12 mois en labels
- Contenir les données suivantes :
[1200, 980, 1450, 1320, 1800, 1650, 2100, 1950, 1700, 2050, 2300, 2700] - Utiliser la couleur
rgba(255, 159, 64, 0.6)pour le fond etrgb(255, 159, 64)pour la bordure - Avoir un titre :
Visiteurs mensuels de la boutique
Une solution
Vous devez être connecté pour voir le contenu.
Étape 6 — Afficher le second graphique dans le template
Modifiez templates/dashboard/index.html.twig pour afficher le second graphique sous le premier, dans une nouvelle section avec son propre titre.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 7 — Ajouter une comparaison sur le graphique des ventes
Modifiez uniquement la partie $chartVentes du contrôleur pour ajouter une seconde série représentant les ventes de l'année précédente, avec les données suivantes :
- Label :
Ventes 2023 (en €) - Données :
[2800, 2400, 3600, 3200, 4500, 4100, 5300, 4800, 4200, 5000, 5600, 6400] - Couleur de fond :
rgba(255, 99, 132, 0.6) - Couleur de bordure :
rgb(255, 99, 132)
Le template Twig n'a pas besoin d'être modifié.
Une solution
Vous devez être connecté pour voir le contenu.